const jwt = require('jsonwebtoken');
const { AppError } = require('../middlewares/errorHandler');
const { User, Role, Permission } = require('../models');
const wechatService = require('./wechatService');
const config = require('../config');
const { Op } = require('sequelize');

class AuthService {
  /**
   * 生成JWT令牌
   * @param {number} userId - 用户ID
   * @returns {string} - JWT令牌
   */
  generateToken(userId) {
    return jwt.sign({ id: userId }, config.jwt.secret, {
      expiresIn: config.jwt.expiresIn
    });
  }

  /**
   * 用户登录
   * @param {Object} credentials - 登录凭证
   * @param {string} platform - 登录平台
   * @returns {Promise<Object>} - 登录结果
   */
    async login(credentials, platform) {
    let user;

    switch (platform) {
      case 'web':
      case 'app':
        if (!credentials.username || !credentials.password) {
          throw new AppError(400, 'Please provide username and password');
        }
        
        user = await User.scope('withPassword').findOne({
          where: { username: credentials.username }
        });

        if (!user || !(await user.validatePassword(credentials.password))) {
          throw new AppError(401, 'Invalid credentials');
        }
        break;

      case 'wechat':
        if (!credentials.appId || !credentials.code) {
          throw new AppError(400, 'Please provide appId and code');
        }
        
        const session = await wechatService.code2Session(credentials.appId, credentials.code);
        user = await User.findOne({
          where: { wechat_open_id: session.openid }
        });
        
        if (!user) {
          // Create new user if not exists
          user = await User.create({
            username: `wx_${session.openid.substr(0, 8)}`,
            wechat_open_id: session.openid,
            wechat_union_id: session.unionid,
            last_login_platform: 'wechat'
          });
        }
        break;

      default:
        throw new AppError(400, 'Invalid login platform');
    }

    // Update last login info
    await user.update({
      last_login_at: new Date(),
      last_login_platform: platform
    });

    const token = this.generateToken(user.id);

    return {
      token,
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        phone_number: user.phone_number,
        role: user.role,
        last_login_at: user.last_login_at,
        last_login_platform: user.last_login_platform
      }
    };
  }

  /**
   * 验证JWT令牌
   * @param {string} token - JWT令牌
   * @returns {Promise<Object>} - 验证结果
   */
  async verifyToken(token) {
    try {
      const decoded = jwt.verify(token, config.jwt.secret);

      // 检查令牌是否过期
      const currentTimestamp = Math.floor(Date.now() / 1000);
      if (decoded.exp && decoded.exp < currentTimestamp) {
        throw new AppError(401, '令牌已过期，请重新登录');
      }

      const user = await User.findByPk(decoded.id);
      
      if (!user) {
        throw new AppError(401, '用户不存在');
      }

      if (!user.is_active) {
        throw new AppError(401, '用户账号已被禁用');
      }

      // 更新最后活动时间
      await user.update({ last_active_at: new Date() });
      
      return user;
    } catch (error) {
      if (error instanceof AppError) {
        throw error;
      }
      if (error.name === 'JsonWebTokenError') {
        throw new AppError(401, '无效的令牌');
      }
      if (error.name === 'TokenExpiredError') {
        throw new AppError(401, '令牌已过期，请重新登录');
      }
      throw new AppError(401, '令牌验证失败');
    }
  }

  /**
   * 用户注册
   * @param {Object} userData - 用户数据
   * @param {string} platform - 注册平台
   * @returns {Promise<Object>} - 注册结果
   */
  async register(userData, platform = 'web') {
    // 检查用户是否已存在
    const existingUser = await User.findOne({
      where: {
        [Op.or]: [
          { username: userData.username },
          { email: userData.email },
          { phone_number: userData.phone_number }
        ]
      }
    });

    if (existingUser) {
      throw new AppError(400, '用户已存在');
    }

    // 创建新用户
    const user = await User.create({
      ...userData,
      last_login_platform: platform
    });

    const token = this.generateToken(user.id);

    return {
      token,
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        phone_number: user.phone_number,
        role: user.role,
        last_login_at: user.last_login_at,
        last_login_platform: user.last_login_platform
      }
    };
  }

  /**
   * 用户登出
   * @param {number} userId - 用户ID
   * @returns {Promise<boolean>} - 登出结果
   */
  async logout(userId) {
    // Update last login time
    await User.update(
      { last_login_at: new Date() },
      { where: { id: userId } }
    );
    
    return true;
  }

  /**
   * 获取用户信息
   * @param {number} userId - 用户ID
   * @returns {Promise<Object>} - 用户信息
   */
  async getProfile(userId) {
    const user = await User.findByPk(userId, {
      attributes: { exclude: ['password'] }
    });

    if (!user) {
      throw new AppError(404, '用户不存在');
    }

    return user;
  }

  /**
   * 更新用户信息
   * @param {number} userId - 用户ID
   * @param {Object} updates - 更新数据
   * @returns {Promise<Object>} - 更新后的用户信息
   */
  async updateProfile(userId, updates) {
    const user = await User.findByPk(userId);

    if (!user) {
      throw new AppError(404, '用户不存在');
    }

    // 如果更新包含密码，需要加密
    if (updates.password) {
      updates.password = await user.hashPassword(updates.password);
    }

    // 不允许更新某些字段
    delete updates.role;
    delete updates.is_active;
    delete updates.last_login_at;
    delete updates.last_login_platform;

    await user.update(updates);

    // 返回更新后的用户信息（不包含密码）
    const updatedUser = await User.findByPk(userId, {
      attributes: { exclude: ['password'] }
    });

    return updatedUser;
  }

  /**
   * 获取用户权限
   * @param {number} userId - 用户ID
   * @returns {Promise<Array<string>>} - 权限列表
   */
  async getUserPermissions(userId) {
    const user = await User.findByPk(userId, {
      include: [{
        model: Role,
        include: [{
          model: Permission,
          through: { attributes: [] }
        }]
      }]
    });

    if (!user) {
      throw new AppError(404, '用户不存在');
    }

    // 收集所有权限
    const permissions = new Set();
    user.Roles.forEach(role => {
      role.Permissions.forEach(permission => {
        permissions.add(permission.code);
      });
    });

    return Array.from(permissions);
  }
}

module.exports = new AuthService(); 